package com.example.droolstool.service;

import com.example.droolstool.base.Constants;
import com.example.droolstool.dao.ServiceAssembleModule;
import com.example.droolstool.map.ServiceAssembleMapper;
import com.example.droolstool.module.*;
import com.google.common.collect.Maps;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.StringWriter;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author 赵云龙
 * @Date 2020/6/26
 * @Description TODO
 */

@Service
public class ServerRegisterServiceImpl {


    @Resource
    ServiceAssembleMapper assembleMapper;

    /**
     *  解析规则：
     * 1. 解析节点， 找到节点的from  和  to， 从from 开始  到to  结束
     * 2. 记录已经执行过的节点和无toID 的节点  定义成规则中的全局变量
     * 2. 规则when 中执行判断条件为 fromId 是否被包含在已经执行过的节点集合中
     * 3. 规则中then  执行逻辑
     *    3.1   首先执行当前id 的服务逻辑
     *    3.2   然后从节点的 id  和  to  找到对应的edge， 然后执行 执行完之后  动态执行规则文件
     * 4. 当无toId 的节点全部执行完之后  此规则 返回: 执行完成
     * 写入规则逻辑：
     *   1. 导入模板（包含package，dialect, import global）
     *   2. 每一个节点都是一个规则（rule） 名称 为当前节点的id
     *   3. 规则定义 lock-on-active属性 为true
     *   4. when 中统一为 $drlMessageModule :DrlMessageModule( fromId memberOf executedDrlIds )
     *   5. then 中统一为 $drlMessageModule.executeDrlServer();//  执行 调取服务逻辑
     *   6. end
     * @param serverAssembleModule
     * @return
     */
    public String serverRegister(ServerAssembleModule serverAssembleModule) throws Exception {

        if (serverAssembleModule == null) {
            throw new Exception("服务注册的服务调配请求参数为空！");
        }
        Constants.serverAssembleModule = serverAssembleModule;
//        List<EdgeModule> edgeModules = serverAssembleModule.getEdgeModules();
        List<ServerNodeModule> serverNodeModules = serverAssembleModule.getServiceNodeModules();
        String serverRegisterId = serverAssembleModule.getServiceRegisterId();
        if (!CollectionUtils.isEmpty(serverNodeModules)) {
//            List<DrlMessageModule> drlRuleNameList = serverNodeModules.stream().map(serverNodeModule ->{
//                drlRuleTemplateModule.setRuleName(serverNodeModule.getId());
//                return drlRuleTemplateModule;
//            }).collect(Collectors.toList());
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
            configuration.setClassForTemplateLoading(ServerRegisterServiceImpl.class, "/templates/");
            Template template = configuration.getTemplate("server_assemble.ftl");
            Map<String, Object> params = Maps.newHashMap();
            params.put("drlMessageModules", serverNodeModules);
            try (Writer writer = new StringWriter();){
                template.process(params, writer);
                writer.flush();
                StringBuffer stringBuffer = ((StringWriter) writer).getBuffer();
                String ruleDrl = stringBuffer.toString();
                System.out.println("the ruleDrl is : " + ruleDrl);
                if (Constants.drlMap == null) {
                    Constants.drlMap = Maps.newHashMap();
                }
                Constants.drlMap.put(serverRegisterId, ruleDrl);
                saveServerAssemble(serverRegisterId, ruleDrl);
            } catch (Exception e){
                e.printStackTrace();
            }

            startExecuteDrl(serverAssembleModule);
            endExecuteDrl(serverAssembleModule);
        }
            return StringUtils.EMPTY;
    }

    /**
     *
     * @param serverAssembleModule
     */
    public void startExecuteDrl(ServerAssembleModule serverAssembleModule){
        List<ServerNodeModule> serverNodeModules = serverAssembleModule.getServiceNodeModules();
       Constants.startExecuteDrlIds = serverNodeModules.stream().filter(serverNodeModule ->
             serverNodeModule.getFromId() ==null || CollectionUtils.isEmpty(serverNodeModule.getFromId())
        ).map(ServerNodeModule::getId).collect(Collectors.toList());
    }

    /**
     *
     * @param serverAssembleModule
     */
    public void endExecuteDrl(ServerAssembleModule serverAssembleModule){
        List<ServerNodeModule> serverNodeModules = serverAssembleModule.getServiceNodeModules();
        Constants.endExecuteDrlIds = serverNodeModules.stream().filter(serverNodeModule ->
                serverNodeModule.getToId() ==null || CollectionUtils.isEmpty(serverNodeModule.getToId())
        ).map(ServerNodeModule::getId).collect(Collectors.toList());
    }

    private void saveServerAssemble(String serverRegisterId, String ruleDrl ) {
        if (StringUtils.isNoneBlank(serverRegisterId)) {
            ServiceAssembleModule serviceAssembleModule = new ServiceAssembleModule();
            serviceAssembleModule.setSsfwId(serverRegisterId);
            serviceAssembleModule.setRuleDrl(ruleDrl);
            assembleMapper.updateById(serviceAssembleModule);
        }
    }

}
